package mhttp

import (
	"crypto/tls"
	"io"
	"net"
	"net/http"
	"net/url"
	"time"
)

var DefaultClient = &http.Client{
	Transport: &http.Transport{
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
		}).DialContext,
		MaxIdleConns:          500,              // 最大连接数,默认0无穷大
		MaxIdleConnsPerHost:   500,              // 对每个host的最大连接数量(MaxIdleConnsPerHost<=MaxIdleConns)
		IdleConnTimeout:       30 * time.Second, // 多长时间未使用自动关闭连接
		TLSClientConfig:       &tls.Config{InsecureSkipVerify: true},
		TLSHandshakeTimeout:   10 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
	},
	Timeout: 10 * time.Second,
}
var DefaultHttpHandlerInstance = DefaultHttpHandler{}

type HttpHandler interface {
	Run(request Request, body io.Reader) (*Response, error)
}

type DefaultHttpHandler struct {
}

func (me DefaultHttpHandler) Run(ce Request, body io.Reader) (*Response, error) {
	rowUrl := ce.Url
	if ce.Params != nil {
		if d, err := URL(ce.Url, ce.Params); err != nil {
			return nil, err
		} else {
			rowUrl = d
		}
	}

	if request, err := http.NewRequest(ce.Method, rowUrl, body); err == nil {
		request.Header = ce.Head
		if response, err := DefaultClient.Do(request); err == nil {
			result := &Response{
				Method:        ce.Method,
				Url:           ce.Url,
				Header:        response.Header,
				Status:        response.Status,
				StatusCode:    response.StatusCode,
				OK:            response.StatusCode == 200,
				ContentLength: response.ContentLength,
				Metadata:      response,
				reader:        false,
			}
			response.Cookies()
			return result, err
		} else {
			return nil, err
		}
	} else {
		return nil, err
	}
}

func Head(url string) (*Response, error) {
	if response, err := DefaultClient.Head(url); err == nil {
		result := &Response{
			Method:     "GET",
			Url:        url,
			Header:     response.Header,
			Status:     response.Status,
			StatusCode: response.StatusCode,
			Metadata:   response,
		}
		return result, err
	} else {
		return nil, err
	}
}

func NewRequest(method, url string) *Request {
	return &Request{Method: method, Url: url, Head: make(http.Header), Charset: "utf-8", Handler: DefaultHttpHandlerInstance}
}
func NewRequest2(method, url, headerName, headerValue string) *Request {
	request := NewRequest(method, url)
	request.AddHeader(headerName, headerValue)
	return request
}
func NewRequest3(method, url string, header map[string]string) *Request {
	request := NewRequest(method, url)
	request.AddHeaderMap(header)
	return request
}

func URL(rawURL string, params map[string]string) (string, error) {
	if u, err := url.Parse(rawURL); err == nil {
		if params == nil {
			return rawURL, nil
		}
		values := u.Query()
		for k, v := range params {
			values.Add(k, v)
		}
		return u.String() + "?" + values.Encode(), nil
	} else {
		return "", err
	}
}
